/*===========================================================================
  Copyright (C) 2014 by the Okapi Framework contributors
-----------------------------------------------------------------------------
  This library is free software; you can redistribute it and/or modify it 
  under the terms of the GNU Lesser General Public License as published by 
  the Free Software Foundation; either version 2.1 of the License, or (at 
  your option) any later version.

  This library is distributed in the hope that it will be useful, but 
  WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
  General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License 
  along with this library; if not, write to the Free Software Foundation, 
  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

  See also the full LGPL text here: http://www.gnu.org/copyleft/lesser.html
===========================================================================*/

package net.sf.okapi.v2.common;

/**
 * Collection of common utility functions.
 */
public class U {

	/**
	 * Converts a pair of special characters denoting a tag reference into the key to access the tag.
	 * @param ch1 the first character.
	 * @param ch2 the second character.
	 * @return the key for the given tag reference.
	 * @see #toRef(int)
	 */
	public static int toKey (int ch1,
		int ch2)
	{
		return ((ch1 << 16) | ch2);
	}

	/**
	 * Converts a key to a pair of special characters denoting a tag reference.
	 * @param key the key to convert.
	 * @return a string of two special characters.
	 * @see #toKey(int, int)
	 */
	public static String toRef (int key) {
		return ""+(char)(key >> 16)+(char)key;
	}

	/**
	 * Helper method that checks if a given character is the first special character
	 * of a tag reference.
	 * @param ch the character to check.
	 * @return true if the given character is the first character of a tag reference.
	 */
	public static boolean isChar1 (char ch) {
		switch ( ch ) {
		case C.CODE_STANDALONE:
		case C.CODE_OPENING:
		case C.CODE_CLOSING:
		case C.MARKER_OPENING:
		case C.MARKER_CLOSING:
		case C.PCONT_STANDALONE:
			return true;
		}
		return false;
	}

	/**
	 * Helper methods that indicates if a given string is null or empty.
	 * @param value the string to check.
	 * @return true if the string is either null or empty, false otherwise.
	 */
	public static boolean isNoE(String value) {
		return (( value == null ) || value.isEmpty() );
	}

	/**
	 * Verifies if a given value is a valid NMTOKEN value.
	 * Empty and null values are not valid.
	 * @param value the value to check.
	 * @return true if it is a valid NMTOKEN, false otherwise.
	 */
	public static boolean isNmtoken (String value) {
		if (( value == null ) || value.isEmpty() ) return false;
		// See http://www.w3.org/TR/REC-xml/#NT-Nmtoken
		// ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF]
		// | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF]
		// | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
		// | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
		final int length = value.length();
		for (int i=0; i<length; ) {
			final int cp = value.codePointAt(i);
			switch ( cp ) {
			case ':':
			case '_':
			case '-':
			case '.':
			case '\u00b7':
				break;
			default:
				if (( cp >= 'A' && cp <= 'Z' ) || ( cp >= 'a' && cp <= 'z' )
					|| ( cp >= '0' && cp <= '9' )
					|| ( cp >= '\u00c0' && cp <= '\u00d6' )
					|| ( cp >= '\u00d8' && cp <= '\u00f6' )
					|| ( cp >= '\u00f8' && cp <= '\u02ff' )
					|| ( cp >= '\u0370' && cp <= '\u037d' )
					|| ( cp >= '\u037f' && cp <= '\u1fff' )
					|| ( cp >= '\u200c' && cp <= '\u200d' )
					|| ( cp >= '\u2070' && cp <= '\u218f' )
					|| ( cp >= '\u2c00' && cp <= '\u2fef' )
					|| ( cp >= '\u3001' && cp <= '\ud7ff' )
					|| ( cp >= '\uf900' && cp <= '\ufdcf' )
					|| ( cp >= '\ufdf0' && cp <= '\ufffd' )
					|| ( cp >= '\u0300' && cp <= '\u036f' )
					|| ( cp >= '\u203f' && cp <= '\u2040' )
					|| ( cp >= 0x10000 && cp <= 0xeffff ))
				{
					break;
				}
				else {
					return false;
				}
			}
			i += Character.charCount(cp);
		}
		return true;
	}

}
